package ru.volgogradetzzz.threeD.interactors {
	import flash.display.Stage;
	import flash.events.MouseEvent;
	import ru.volgogradetzz.math.VMatrix4x4;
	import ru.volgogradetzzz.math.VVector3;
	/**
	 * ...
	 * @author Volgogradetzzz
	 */
	public class ModelRotator {
		private const _AXIS:VVector3 = new VVector3();
		private const _PREV_MOUSE_POS:VVector3 = new VVector3();
		private const _CURR_MOUSE_POS:VVector3 = new VVector3();
		private const _DIFF:VVector3 = new VVector3();
		private const _MODEL_ROTATION_CURR:VMatrix4x4 = new VMatrix4x4();
		
		private var _stage:Stage;
		private var _mousePressed:Boolean = false;
		private var _rotationSpeed:Number = 0;
		
		public function ModelRotator(stage:Stage) {
			_stage = stage;
			
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
		}
		
		public function update(cameraRotation:VMatrix4x4, modelRotation:VMatrix4x4):void {
			_MODEL_ROTATION_CURR.identity();
			
			if (_mousePressed) {
				_rotationSpeed = 0;
				
				_CURR_MOUSE_POS.x = _stage.mouseX;
				_CURR_MOUSE_POS.y = _stage.mouseY;
				
				_CURR_MOUSE_POS.subtractCopyTo(_PREV_MOUSE_POS, _DIFF);
				
				_rotationSpeed = _DIFF.squareMagnitude() * 0.001;
				if (_rotationSpeed > 0.2) {
					_rotationSpeed = 0.2;
				}
				
				_AXIS.x = -_DIFF.y;
				_AXIS.y = -_DIFF.x;
				_AXIS.z = 0;
				_AXIS.multiplyByMatrix(cameraRotation);
				_AXIS.normalize();
				
				_PREV_MOUSE_POS.x = _stage.mouseX;
				_PREV_MOUSE_POS.y = _stage.mouseY;
			}else {
				_rotationSpeed *= 0.95;
			}
			
			if (_rotationSpeed > 0.0001) {
				var c:Number = Math.cos(_rotationSpeed);
				var s:Number = Math.sin(_rotationSpeed);
				var t:Number = 1 - c;
				
				_MODEL_ROTATION_CURR.m11 = t * _AXIS.x * _AXIS.x + c;
				_MODEL_ROTATION_CURR.m12 = t * _AXIS.x * _AXIS.y + s * _AXIS.z;
				_MODEL_ROTATION_CURR.m13 = t * _AXIS.x * _AXIS.z - s * _AXIS.y;
				
				_MODEL_ROTATION_CURR.m21 = t * _AXIS.x * _AXIS.y - s * _AXIS.z;
				_MODEL_ROTATION_CURR.m22 = t * _AXIS.y * _AXIS.y + c;
				_MODEL_ROTATION_CURR.m23 = t * _AXIS.y * _AXIS.z + s * _AXIS.x;
				
				_MODEL_ROTATION_CURR.m31 = t * _AXIS.x * _AXIS.z + s * _AXIS.y;
				_MODEL_ROTATION_CURR.m32 = t * _AXIS.y * _AXIS.z - s * _AXIS.x;
				_MODEL_ROTATION_CURR.m33 = t * _AXIS.z * _AXIS.z + c;
				
				modelRotation.multiplyByMatrix(_MODEL_ROTATION_CURR);
			}
		}
		
		private function mouseDown(event:MouseEvent):void {
			_mousePressed = true;
			
			_PREV_MOUSE_POS.x = _stage.mouseX;
			_PREV_MOUSE_POS.y = _stage.mouseY;
		}
		
		private function mouseUp(event:MouseEvent):void {
			_mousePressed = false;
		}
	}
}